package cn.leedsoft.luma.common;

import cn.leedsoft.luma.exception.HttpParametersValidException;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import javax.validation.constraints.NotNull;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * Created by leeds on 2016/7/5 15:01.
 */
public class Reply {
    private Reply() {
    }

    private Object data;//实际返回的json数据
    private Integer errcode;//只有返回状态码为非0时，才会返回错误码、错误信息
    private String errmsg;
    private ReplyStatusEnum status;//返回状态

    /**
     * 如果不设置errcode，则默认去status中的状态码
     * @return
     */
    public Integer getErrcode() {
        if(errcode == null && status != null) {
            errcode = status.getCode();
        }
        return errcode;
    }

    public void setErrcode(Integer errcode) {
        this.errcode = errcode;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getErrmsg() {
        return errmsg;
    }

    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }

    public ReplyStatusEnum getStatus() {
        return status;
    }

    public void setStatus(ReplyStatusEnum status) {
        this.status = status;
    }

    public enum ReplyStatusEnum {
        SUCCESS(0, "成功"), SUCCESS_EMPTY(0, "结果为空"),//成功，errcode 为0
        FAIL(100, "失败"), FAIL_PARAMS_VALID(101, "参数验证失败"),//errcode 100以上为错误码。101~199之间，是参数验证错误。
        FAIL_BUSINESS_ERROR(200, "业务逻辑错误");//200以上，是业务逻辑错误。
        private int code;
        private String name;

        ReplyStatusEnum(int code, String name) {
            this.code = code;
            this.name = name;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void valid(BindingResult bindingResult) {
        Assert.notNull(bindingResult);

        if (bindingResult.hasErrors()) {
            Reply reply = new Reply();
            reply.setStatus(ReplyStatusEnum.FAIL_PARAMS_VALID);
            Map<String, String> errMap = Maps.newHashMap();
            for (FieldError error : bindingResult.getFieldErrors()) {
                errMap.put(error.getField(), error.getDefaultMessage());
            }
            reply.setErrmsg(errMap.toString());
            throw new HttpParametersValidException(JSON.toJSONString(reply));
        }
    }

    public static Reply success(Object data) {
        Reply reply = new Reply();
        if (data == null || data.getClass().isArray() && Array.getLength(data) == 0
                || (data instanceof Collection) && ((Collection) data).size() == 0
                || (data instanceof Map) && ((Map)data).size() == 0) {
            reply.setStatus(ReplyStatusEnum.SUCCESS_EMPTY);
        } else {
            reply.setStatus(ReplyStatusEnum.SUCCESS);
        }

        reply.setData(data);
        return reply;
    }

    /**
     *
     * @param errcode 约定：应该定义为100以上的数字。默认错误码是100。101~199之间，是参数验证错误。200以上，是业务逻辑错误。
     * @param errmsg
     * @return
     */
    public static Reply fail(int errcode, String errmsg) {
        Reply reply = new Reply();
        reply.setStatus(ReplyStatusEnum.FAIL);
        reply.setErrcode(errcode);
        reply.setErrmsg(errmsg);
        return reply;
    }

    public static Reply fail(String errmsg) {
        return fail(ReplyStatusEnum.FAIL.getCode(), errmsg);
    }
}
